/**
 *    Copyright 2012 Geensoft S.A.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 **/
package ar.com.greensoft.neo.web.jsf.util;

import java.util.Calendar;
import java.util.Date;

import org.joda.time.DateTime;
import org.joda.time.Period;

/**
 * @author Jorge E. Villaverde
 * @version 1.0.0
 * @since 27/01/2012	
 */
public class DateUtils {

	public static long hoursBetween(final Calendar startDate, final Calendar endDate) {
		DateTime startTime = new DateTime(startDate);
		DateTime endTime = new DateTime(endDate);
		
		Period p = new Period(startTime, endTime);
		long hours = p.getHours();
		return hours;
	}
	
	public static long daysBetween(final Date startDate, final Date endDate) {
		Calendar startCal = Calendar.getInstance();
		Calendar endCal = Calendar.getInstance();
		startCal.setTime(startDate);
		endCal.setTime(endDate);
		return daysBetween(startCal, endCal);
	}
	
	public static long daysBetween(final Calendar startDate, final Calendar endDate) {
		Calendar sDate = (Calendar) startDate.clone();
		long daysBetween = 0;

		int y1 = sDate.get(Calendar.YEAR);
		int y2 = endDate.get(Calendar.YEAR);
		int m1 = sDate.get(Calendar.MONTH);
		int m2 = endDate.get(Calendar.MONTH);

		//**year optimization**
		while (((y2 - y1) * 12 + (m2 - m1)) > 12) {

			//move to Jan 01
			if ( sDate.get(Calendar.MONTH) == Calendar.JANUARY
				 && sDate.get(Calendar.DAY_OF_MONTH) == sDate.getActualMinimum(Calendar.DAY_OF_MONTH)) {

				daysBetween += sDate.getActualMaximum(Calendar.DAY_OF_YEAR);
				sDate.add(Calendar.YEAR, 1);
			} else {
				int diff = 1 + sDate.getActualMaximum(Calendar.DAY_OF_YEAR) - sDate.get(Calendar.DAY_OF_YEAR);
				sDate.add(Calendar.DAY_OF_YEAR, diff);
				daysBetween += diff;
			}
			y1 = sDate.get(Calendar.YEAR);
		}

		//** optimize for month **
		//while the difference is more than a month, add a month to start month
		while ((m2 - m1) % 12 > 1) {
			daysBetween += sDate.getActualMaximum(Calendar.DAY_OF_MONTH);
			sDate.add(Calendar.MONTH, 1);
			m1 = sDate.get(Calendar.MONTH);
		}

		// process remainder date
		while (sDate.before(endDate)) {
			sDate.add(Calendar.DAY_OF_MONTH, 1);
			daysBetween++;
		}

		return daysBetween;
	}

	public static long hoursBetween(Date horaInicio, Date horaFin) {
		Calendar startCal = Calendar.getInstance();
		Calendar endCal = Calendar.getInstance();
		startCal.setTime(horaInicio);
		endCal.setTime(horaFin);
		return hoursBetween(startCal, endCal);
	}
	
	public static int getYear(Date date){
		Calendar cal = Calendar.getInstance();
		cal.setTime(date);
		int year = cal.get(Calendar.YEAR);
		return year;
	}

	public static int getMonth(Date date){
		Calendar cal = Calendar.getInstance();
		cal.setTime(date);
		int month = cal.get(Calendar.MONTH);
		return month;		
	}

	public static Date getDateFromYear(int year){
		return getDateFromMonth(year, Calendar.JANUARY);
	}
	
	public static Date getDateFromMonth(int year, int month){
	    Calendar cal = Calendar.getInstance();
	    //Clear all fields
	    cal.clear();
	    cal.set(Calendar.YEAR, year);
	    cal.set(Calendar.MONTH, month);
	    cal.set(Calendar.DATE, 1);
	    return cal.getTime();		
	}
}
